#pragma once
#include<iostream>
#include<pthread.h>
#include<string>
#include<queue>
#include<vector>
#include"Sem.hpp"
// template<typename T>
// class BlockQueue
// {
//     public:
//     BlockQueue(int cap)
//     :_cap(cap)
//     {
//         _productor_wait_num=0;
//         _consumer_wait_num=0;
//         pthread_mutex_init(&_mutex,nullptr);
//         pthread_cond_init(&_product_cond,nullptr);
//         pthread_cond_init(&_consum_cond,nullptr);
//     }
//     void Enqueue(T& in)//生产者用的接口
//     {
//         pthread_mutex_lock(&_mutex);
//         while(IsFull())
//         {
//             _productor_wait_num++;
//             pthread_cond_wait(&_product_cond,&_mutex);
//             _productor_wait_num--;
//         }
//         _block_queue.push(in);
//         std::cout<<"一个任务被放入"<<std::endl;
//         if(_consumer_wait_num>0)
//             pthread_cond_signal(&_consum_cond);
//         pthread_mutex_unlock(&_mutex);
//     }
//     void Pop(T* out)
//     {
//         pthread_mutex_lock(&_mutex);
//         while(IsEmpty())
//         {
//             _consumer_wait_num++;
//             pthread_cond_wait(&_consum_cond,&_mutex);
//             _consumer_wait_num--;
//         }
//         *out=_block_queue.front();
//         _block_queue.pop();
//         std::cout<<"一个任务被取走"<<std::endl;
//         if(_productor_wait_num>0)
//             pthread_cond_signal(&_product_cond);
//         pthread_mutex_unlock(&_mutex);
//     }
//     bool IsEmpty()
//     {
//         return _block_queue.size()==0;
//     }
//     bool IsFull()
//     {
//         return _block_queue.size()==_cap;
//     }
//     ~BlockQueue()
//     {
//         pthread_cond_destroy(&_product_cond);
//         pthread_cond_destroy(&_consum_cond);
//         pthread_mutex_destroy(&_mutex);
//     }
//     private:
//     std::queue<T> _block_queue;
//     int _cap;
//     pthread_mutex_t _mutex;//保护block queue的锁
//     pthread_cond_t _product_cond;//专⻔给⽣产者提供的条件变量
//     pthread_cond_t _consum_cond;// 专⻔给消费者提供的条件变量
//     int _productor_wait_num;
//     int _consumer_wait_num;
// };

template<typename T>
class BlockQueue
{
    private:
    void Lock(pthread_mutex_t& mutex)
    {
        pthread_mutex_lock(&mutex);
    }
    void UnLock(pthread_mutex_t& mutex)
    {
        pthread_mutex_unlock(&mutex);
    }
    public:
    BlockQueue(int cap)
    :_ring_queue(cap),_cap(cap),_room_sem(_cap),_data_sem(0),_productor_step(0),_consumer_step(0)
    {
        pthread_mutex_init(&_productor_mutex,nullptr);
        pthread_mutex_init(&_consumer_mutex,nullptr);
    }
    void Enqueue(T& in)//生产者用的接口
    {
        Lock(_productor_mutex);
        _room_sem.P();
        _ring_queue[_productor_step++]=in;
        _productor_step%=_cap;
        std::cout<<"一个任务被放入"<<std::endl;
        UnLock(_productor_mutex);
        _data_sem.V();
    }
    void Pop(T* out)
    {
        Lock(_consumer_mutex);
        _data_sem.P();
        *out=_ring_queue[_consumer_step++];
        _consumer_step%=_cap;
        std::cout<<"一个任务被取走"<<std::endl;
        UnLock(_consumer_mutex);
        _room_sem.V();
    }
    ~BlockQueue()
    {
        pthread_mutex_destroy(&_productor_mutex);
        pthread_mutex_destroy(&_consumer_mutex);
    }
    private:
    std::vector<T> _ring_queue;
    int _cap;
    pthread_mutex_t _productor_mutex;
    pthread_mutex_t _consumer_mutex;
    Sem _room_sem;//生产者关心
    Sem _data_sem;//消费者关心

    int _productor_step;//生产者下标
    int _consumer_step;//消费者下标
};